package org.zjvis.datascience.web.controller;

import cn.hutool.crypto.digest.BCrypt;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import javax.security.auth.login.LoginException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.zjvis.datascience.common.dto.user.UserDTO;
import org.zjvis.datascience.common.model.ApiResult;
import org.zjvis.datascience.common.model.ApiResultCode;
import org.zjvis.datascience.common.util.RSAUtil;
import org.zjvis.datascience.common.vo.user.UserLoginVO;
import org.zjvis.datascience.common.vo.user.UserTokenVO;
import org.zjvis.datascience.service.LoginService;
import org.zjvis.datascience.service.PasswordService;
import org.zjvis.datascience.service.UserService;

import java.time.Instant;
import java.util.Map;

/**
 * @description 系统登录 Controller
 * @date 2021-12-13
 */
@Api(tags = "系统登录")
@RestController
@RequestMapping("/auth")
public class LoginController {
    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    private final static Logger logger = LoggerFactory.getLogger(LoginController.class);
    @Value("${login.tianshu.salt}")
    final String salt = "abcde";
    @Autowired
    private LoginService loginService;
    @Value("${login.tianshu.code.timeout}")
    private long timeout;
    @Autowired
    private PasswordService passwordService;

    @Autowired
    private UserService userService;

    @ApiOperation("登录")
    @PostMapping(value = "/login")
    public ApiResult<UserTokenVO> login(@Valid @RequestBody UserLoginVO vo) throws Exception {
        try {
            return ApiResult.valueOf(loginService.login(vo));
        } catch (LoginException e) {
            logger.warn("someone trying to hack system with incorrect pwd");
            return ApiResult.valueOf(ApiResultCode.NO_AUTH, null, e.getMessage());
        }
    }
    @ApiOperation("天枢登录")
    @PostMapping(value = "/login/tianshu")
    public ApiResult<UserTokenVO> TianshuLogin( @RequestBody JSONObject params, @Value("${login.tianshu.key.private}") String privateKey) throws Exception {
        String tianshuCode = params.getString("tianshu_code");
        String user = RSAUtil.privateDecrypt(tianshuCode, RSAUtil.getPrivateKey(privateKey));
        Map<String, String> userInfo = OBJECT_MAPPER.readValue(user, new TypeReference<Map<String, String>>() {
        });
        String username = userInfo.get("username");
        String phone = userInfo.get("iphone");
        String userId = userInfo.get("id");
        String timestamp = userInfo.get("timestamp");
        String password = OBJECT_MAPPER.writeValueAsString(ImmutableMap.of(
                "id", userId,
                "salt", salt));
        String tianshuUsername = "tianshu_" + username;
        long time = Instant.now().toEpochMilli() - Long.valueOf(timestamp);
        if (time > timeout) {
            throw new Exception("token已过期");
        }
        UserDTO tianshuUser = userService.queryByName(tianshuUsername);
        if (tianshuUser == null) {
            tianshuUser = new UserDTO();
            tianshuUser.setName(tianshuUsername);
            tianshuUser.setPassword(password);
            tianshuUser.setPhone(phone);
            userService.save(tianshuUser);
        }
        // TODO: this is a security risk, change as soon as possible
        UserLoginVO vo = new UserLoginVO(tianshuUser.getName(), password);
        try {
            return ApiResult.valueOf(loginService.login(vo));
        } catch (LoginException e) {
            logger.warn("someone trying to hack system with incorrect pwd");
            return ApiResult.valueOf(ApiResultCode.NO_AUTH, null, e.getMessage());
        }

    }

    @ApiOperation("退出登录")
    @PostMapping(value = "/logout")
    public ApiResult logout() {
        loginService.logout();
        return new ApiResult();
    }

    @ApiOperation("获取用户信息")
    @PostMapping(value = "/info")
    public ApiResult<UserTokenVO> info() {
        return ApiResult.valueOf(loginService.getInfo());
    }

    @ApiOperation("获取公钥")
    @PostMapping(value = "/getPublicKey")
    public ApiResult<String> getPublicKey() {
        return ApiResult.valueOf(passwordService.getPublicKey());
    }

    @ApiOperation("获取登录状态")
    @PostMapping(value = "/getLoginStatus")
    public ApiResult<Boolean> getLoginStatus() {
        return SecurityUtils.getSubject().isRemembered() ? ApiResult.valueOf(true) : ApiResult.valueOf(false);
    }

}
